package repository

import (
	"context"
	"fmt"
	"time"
	"webook/internal/domain"
	"webook/internal/repository/cache"
)

type RankingRepository interface {
	ReplaceTopN(ctx context.Context, arts []domain.Article) error
	GetTopN(ctx context.Context) ([]domain.Article, error)
}

type CachedRankingRepository struct {
	localCache cache.RankingCache
	redisCache cache.RankingCache
}

func NewCachedRankingRepository(localCache *cache.LocalRankingCache, redisCache *cache.RedisRankingCache) RankingRepository {
	return &CachedRankingRepository{
		localCache: localCache,
		redisCache: redisCache,
	}
}

func (repo *CachedRankingRepository) GetTopN(ctx context.Context) ([]domain.Article, error) {
	// 1. 从本地缓存中找TopN
	var key = fmt.Sprintf("ranking:topn")
	arts, err := repo.localCache.Get(ctx, key)
	if err == nil {
		// 本地缓存命中，直接返回
		return arts, nil
	}
	// 2. 找不到再从redis缓存中找
	arts, err = repo.redisCache.Get(ctx, key)
	if err == nil {
		// redis缓存命中
		// 同步本地缓存
		go func() {
			repo.localCache.Set(ctx, key, arts, time.Minute*3)
		}()
		return arts, nil
	}
	// 3. 都找不到返回错误
	// TODO: 强制从本地缓存中返回
	return []domain.Article{}, err
}

func (repo *CachedRankingRepository) ReplaceTopN(ctx context.Context, arts []domain.Article) error {
	var key = fmt.Sprintf("ranking:topn")
	// 1. 先写本地缓存
	err := repo.localCache.Set(ctx, key, arts, time.Minute*3)
	if err != nil {
		return err
	}
	// 2. 再写redis缓存
	return repo.redisCache.Set(ctx, key, arts, time.Minute*3)
}
